package com.study.boot.activiti.controller;

import com.study.boot.activiti.domain.Leave;
import com.study.boot.activiti.domain.ProcessInstanceAndTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 任务控制器
 *
 * @author TangFD@HF 2018/5/2
 */
@Controller
public class TaskController {
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;

    @GetMapping("agency")
    public String agency(Model model) {
        List<Task> taskList = taskService.createTaskQuery().taskCandidateGroup("leaderId").list();
        List<ProcessInstanceAndTask> processInstanceAndTasks = new ArrayList<>(taskList.size());
        for (Task task : taskList) {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            processInstanceAndTasks.add(getProcessInstanceAndTask(task, processInstance));
        }

        model.addAttribute("processInstances", processInstanceAndTasks);
        return "agency";
    }

    private ProcessInstanceAndTask getProcessInstanceAndTask(Task task, ProcessInstance processInstance) {
        ProcessInstanceAndTask processInstanceAndTask = new ProcessInstanceAndTask(processInstance);
        processInstanceAndTask.setTask(task);
        Leave leave = (Leave) taskService.getVariable(task.getId(), "leaveParam");
        processInstanceAndTask.setLeave(leave);
        return processInstanceAndTask;
    }

    @GetMapping("tasking")
    public String tasking(Model model) {
        List<ProcessInstance> processInstances = runtimeService.createProcessInstanceQuery().startedBy("userId").list();
        List<ProcessInstanceAndTask> processInstanceAndTasks = new ArrayList<>(processInstances.size());
        for (ProcessInstance processInstance : processInstances) {
            Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
            processInstanceAndTasks.add(getProcessInstanceAndTask(task, processInstance));
        }

        model.addAttribute("processInstances", processInstanceAndTasks);
        return "tasking";
    }

    @GetMapping("history")
    public String history(Model model) {
        HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
        List<HistoricProcessInstance> processInstanceList = historicProcessInstanceQuery.finished().startedBy("userId").list();
        model.addAttribute("processInstances", processInstanceList);
        return "history";
    }

    @GetMapping("adjust")
    public String adjust(Model model) {
        List<Task> taskList = taskService.createTaskQuery().taskCandidateGroup("adjustId").list();
        List<ProcessInstanceAndTask> processInstanceAndTasks = new ArrayList<>(taskList.size());
        for (Task task : taskList) {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            processInstanceAndTasks.add(getProcessInstanceAndTask(task, processInstance));
        }

        model.addAttribute("processInstances", processInstanceAndTasks);
        return "adjust";
    }

    @GetMapping("toApprove")
    public String toApprove(Model model, @RequestParam String taskId) {
        Leave leave = (Leave) taskService.getVariable(taskId, "leaveParam");
        model.addAttribute("leave", leave);
        model.addAttribute("taskId", taskId);
        return "toApprove";
    }

    @PostMapping("approve")
    public String approve(@Valid Leave leave, @RequestParam String taskId, @RequestParam boolean status) {
        Map<String, Object> params = new HashMap<>(2);
        params.put("leaveParam", leave);
        params.put("approve", status);
        taskService.claim(taskId, "userId");
        taskService.complete(taskId, params);
        return "redirect:agency";
    }

    @GetMapping("toAdjust")
    public String toAdjust(Model model, @RequestParam String taskId) {
        Leave leave = (Leave) taskService.getVariable(taskId, "leaveParam");
        model.addAttribute("leave", leave);
        model.addAttribute("taskId", taskId);
        return "toAdjust";
    }

    @PostMapping("adjustContent")
    public String adjustContent(@Valid Leave leave, @RequestParam String taskId) {
        Map<String, Object> params = new HashMap<>(2);
        params.put("leaveParam", leave);
        params.put("adjust", true);
        taskService.claim(taskId, "userId");
        taskService.complete(taskId, params);
        return "redirect:adjust";
    }

    @PostMapping("delAdjust")
    public String delAdjust(@RequestParam String taskId) {
        Map<String, Object> params = new HashMap<>(1);
        params.put("adjust", false);
        taskService.claim(taskId, "userId");
        taskService.complete(taskId, params);
        return "redirect:adjust";
    }
}
